前言
不知道Promise是啥的,请看上一篇《异步流程控制》
看了不少Prmose实现的资料,目前的理解就是Promise也就是回调的一种优雅实现。
现在Javascript的重心都放在了async-await,而async-await是建立在Promise之上的,所以深入一下Promise,还是很有必要的。
实现功能分析
原生Promise
开始实现
创建一个_promise函数,由简到繁
简单功能
源码:
|
|
使用:
|
|
步骤分析:
- 传入fn执行,并调用then方法传入异步执行完毕后的函数赋值给Promise内部的callback
- Promise内部fn执行并将resolve函数作为参数传入
- fn执行到成功位置,执行resolve函数并传入成功值(val)
- resolve函数执行回调callback并传入成功值
链式支持
实现:
在then中返回this,并把then的回调存放到$resolve数组中,执行resolve使用forEach依次调用
可是如果then中的传入函数是同步的话,就无法控制回调执行顺序
比如:
|
|
只会执行fn,回调都没有执行,因为这时在resolve比then先执行,这时候promise.$resolve数组是空数组,所以上面代码只打印了一个1。我们需要把resolve放到下一个任务队列末尾执行,也就是then的回调都添加到了数组中之后
修改resolve函数
|
|
引入状态
分析:
每个 Promise 存在三个互斥状态:pending、fulfilled、rejected。Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。
源码:
promise.value保存之后调用该对象回调的值
使用:
|
|
异步回调返回的结果传递到下一个回调
修改resolve函数
|
|
即可
失败处理
异步操作不可能都成功,在异步操作失败时,标记其状态为 rejected,并执行注册的失败回调。
有了之前处理 fulfilled 状态的经验,支持错误处理变得很容易。毫无疑问的是,在注册回调、处理状态变更上都要加入新的逻辑:
|
|